package juc.blockqueue.priorityblockingqueue;

/**
 * @ClassName PriorityBlockingQueue
 * @PackageName juc.blockqueue.priorityblockingqueue
 * @projectName myThread
 * @Description PriorityBlockingQueue 使用详解
 * @Author games
 * @Date 2025/9/4 上午11:27
 * @Version 1.0
 */

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * PriorityBlockingQueue 使用详解
 * PriorityBlockingQueue 是一个支持优先级排序的无界阻塞队列，它结合了 PriorityQueue 的优先级特性和 BlockingQueue 的阻塞特性。
 * 基本特性
 * 无界队列：理论上容量无限制（受内存限制）
 * 优先级排序：元素按照优先级顺序排列
 * 阻塞特性：当队列为空时，获取元素的操作会阻塞
 * 线程安全：内部使用锁机制保证多线程安全
 * 自然排序：默认按照元素的自然顺序排序，或通过 Comparator 定制排序
 *
 *
 * 主要方法
 * 插入操作
 * put(E e)：插入元素，由于是无界队列，不会阻塞
 * offer(E e)：插入元素，立即返回 true
 * add(E e)：插入元素，与 offer 功能相同
 * 移除操作
 * take()：获取并移除队首元素（优先级最高的元素），队列空时阻塞
 * poll()：获取并移除队首元素，队列空时返回 null
 * poll(long timeout, TimeUnit unit)：获取并移除队首元素，可设置超时时间
 * 检查操作
 * peek()：返回队首元素但不移除，队列空时返回 null
 * comparator()：返回用于排序的比较器
 *
 *
 */
public class PriorityBlockingQueueExample {
    public static void main(String[] args) {

        /**
         * 这行代码计算索引为k的节点的父节点在数组中的索引位置。
         *
         * 实现原理
         * 在二叉堆（通常用数组实现）中，节点之间的关系可以通过数学计算得出：
         *
         * 对于任意节点索引k，其父节点的索引为(k-1)/2（向下取整）
         * 左子节点索引为2*k + 1
         * 右子节点索引为2*k + 2
         * 这里使用了无符号右移运算符>>>代替除法：
         *
         * (k - 1) >>> 1等同于(k - 1) / 2（对于非负数）
         * 使用位运算通常比除法运算更高效
         * 用途
         * 这种计算常见于：
         *
         * 堆排序算法实现
         * 优先队列（如Java中的PriorityQueue）
         * 其他基于二叉堆的数据结构
         *
         */
        BlockingQueue<Integer> queue = new PriorityBlockingQueue<>();

        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                queue.put(3);
                System.out.println("Produced: " + 3);
                queue.put(1);
                System.out.println("Produced: " + 1);
                queue.put(2);
                System.out.println("Produced: " + 2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                System.out.println("Consumed: " + queue.take());
                System.out.println("Consumed: " + queue.take());
                System.out.println("Consumed: " + queue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producer.start();
        consumer.start();
    }
}